#pragma once

#include "compiler.hpp"
#include "run.hpp"  
#include <jsoncpp/json/json.h>
#include "../common/Log.hpp"
#include "../common/Util.hpp"
#include <dirent.h>
namespace ns_compile_run
{
    class CompileAndRun{
        public:

        /*
        * json匹配规则
        *输入,json_input
        * code:用户提交的代码
        * input:用户的输入
        * CPU_limit:Second
        * Memory_limit:KB
        * 输出,json_output:
        * status:状态码
        *   *2：一般是系统调用打开文件等操作失败
        *   *3：编译报错
        * reason：请求结果
        * 可能有的输出：
        * stdout:程序运行的输出
        * stderr:程序运行的标准错误输出
        */
        static void Start(const std::string& json_input,std::string  *json_output)
        {
            Json::Value InputValue;
            Json::Value OutValue;
            Json::Reader r;
            r.parse(json_input,InputValue);
            std::string code = InputValue["code"].asString();
            std::string UsrInput = InputValue["input"].asString();
            rlim64_t CPU_limit = InputValue["CPU_limit"].asInt64();
            rlim64_t Memory_limit = InputValue["Memory_limit"].asInt64();


            //系统能提供毫秒级时间戳，以及原子性递增，保证形成文件唯一性
            ns_Util::TempPathUtil::createTempDirectory();
            std::string file_name = ns_Util::FileUtil::TempPathUniqFilename();
            std::string fileSrc =  ns_Util::TempPathUtil::FormSrc(file_name);
            std::string fileError = ns_Util::TempPathUtil::FormError(file_name);
            std::string fileInput = ns_Util::TempPathUtil::StdinPath(file_name);

            //结束时自动执行
            ns_Util::RAII endfunction;
            endfunction._func = [&json_output,&OutValue,&file_name](){
                    *json_output  = OutValue.toStyledString();
                    ns_Util::DirectUtil::cleanDirectoryByFilename(ns_Util::TempPathUtil::temp_path,file_name);
            };

            //形成临时src文件
            if(!ns_Util::FileUtil::WriteToFile(fileSrc,code))
            {
                OutValue["status"] = -2;
                OutValue["reason"] = "形成临时源文件失败\n";
                return ;
            }

            if(!ns_compiler::Compiler::Compile(file_name))
            {
                //编译失败
                OutValue["status"] = -3;
                OutValue["reason"] = ns_Util::FileUtil::ReadFileToString(fileError);
                return;
            }

            ns_Util::FileUtil::WriteToFile(fileInput,UsrInput);
            int ReturnVal = ns_run::Runner::Run(file_name,CPU_limit,Memory_limit);
            if(ReturnVal<0)
            {
                OutValue["status"] = -4;
                OutValue["reason"] = "运行时未知错误\n";
                return;
            }
            else if(ReturnVal >0)
            {
                OutValue["status"] = ReturnVal;
                OutValue["reason"] = strsignal(ReturnVal);
                return ;
            }
            
            OutValue["status"] = ReturnVal;
            OutValue["reason"] = "编译运行成功";
            if(ReturnVal ==0)
            {
                OutValue["stdout"] = ns_Util::FileUtil::ReadFileToString(ns_Util::TempPathUtil::StdoutPath(file_name));
                OutValue["stderr"] = ns_Util::FileUtil::ReadFileToString(ns_Util::TempPathUtil::StderrPath(file_name));
            }
        }
        
    };
};
